/**
 * @file performance.h
 * @brief 统计函数调用性能
 */
#ifndef TIANYU_COMMON_PERFORMANCE_H_
#define TIANYU_COMMON_PERFORMANCE_H_

#include <string>
#include <map>
#include "common_define.h"
#include "clock.h"

namespace common
{

	class CPerfInfo
	{
	public:
		/**
		 * @brief CPerfInfo 默认构造函数
		 */
		CPerfInfo( );
		/**
		 * @brief ~CPerfInfo 默认析构函数
		 */
		~CPerfInfo( );

		/**
		* @brief 增加被调用次数
		*
		* @param elapsed 调用的时间
		*
		* @return 被调用次数
		*/
		int32_t AddCalled( int32_t elapsed );

		/**
		* @brief 重置
		*/
		void Reset( );

		/**
		* @brief 总共被调用次数
		*
		* @return 被调用次数
		*/
		int32_t total_called( ) const { return total_called_; }

		/**
		* @brief 一共消耗时间
		*
		* @return 返回一共消耗时间
		*/
		int32_t cost_time( ) const { return cost_time_; }

		/**
		* @brief 最大消耗时间
		*
		* @return 返回最大消耗时间
		*/
		int32_t most_cost_time( ) const { return most_cost_time_; }


		/**
		* @brief 最少消耗时间
		*
		* @return 返回最少消耗时间
		*/
		int32_t least_cost_time( ) const { return least_cost_time_; }

	private:

		int32_t total_called_;
		int32_t cost_time_;
		int32_t most_cost_time_;
		int32_t least_cost_time_;
	};




	/**
	 * @brief 性能优化，不直接使用string作为map的key,封装CPerfIndex作为key
	 */
	class CPerfIndex
	{
	public:

		/**
		* @brief 构造函数
		*
		* @param hash_code 哈希码
		* @param name 名字
		*/
		CPerfIndex( uint32_t hash_code, const char* name )
		{
			hash_code_ = hash_code;
			name_ = name;
		}

		/**
		* @brief 析构函数
		*/
		~CPerfIndex( ) { }

		/**
		* @brief 获取hash码
		*
		* @return 返回hash码
		*/
		uint32_t hash_code( ) const { return hash_code_; }

		/**
		* @brief 获取名字
		*
		* @return 名字
		*/
		const std::string& name( ) const { return name_; }
	private:

		uint32_t hash_code_;
		std::string name_;
	};



	/**
	 * @brief CPerfIndex的比较函数
	 */
	class CLessPrefIndex
	{
	public:
		bool operator()( const CPerfIndex& __x, const CPerfIndex& __y ) const
		{
			return ( __x.hash_code( ) < __y.hash_code( ) )
				|| ( __x.hash_code( ) == __y.hash_code( ) && __x.name( ) < __y.name( ) );
		}
	};

	typedef std::map<CPerfIndex, CPerfInfo, CLessPrefIndex> PerfMap;
	typedef PerfMap::iterator PerfMapIterator;

	/**
	 * @brief
	 */
	class CPerfStat
	{
	public:

		/**
		* @brief hash散列算法
		*
		* @param str 需要计算hash值得字符串，必须以ASCII 0结尾
		*
		* @return 字符串对应的hash值
		*/
		static inline uint32_t DJBHash( const char* str )
		{
			uint32_t hash = 5381;
			for ( const char* p = str; 0 != *p; ++p )
			{
				hash = ( ( hash << 5 ) + hash ) + *p;
			}
			return ( hash & 0x7FFFFFFF );
		}


		/**
		 * @brief GetPerfInfo 获得函数name的统计信息
		 *
		 * @param name 函数名称
		 *
		 * @return CPerfInfo
		 */
		static inline CPerfInfo& GetPerfInfo( const char* name )
		{
			uint32_t hash_code = DJBHash( name );
			CPerfIndex perf_index( hash_code, name );
			return performance_map_[ perf_index ];
		}

		/**
		 * @brief GetPerfInfo 根据HashCode和函数名称获得统计信息
		 *
		 * @param hashCode hash值
		 * @param name 函数名称
		 *
		 * @return CPerfInfo
		 */
		static inline CPerfInfo& GetPerfInfo( uint32_t hash_code, const char* name )
		{
			CPerfIndex perf_index( hash_code, name );
			return performance_map_[ perf_index ];
		}

		static PerfMap& GetPerfMap( ) { return performance_map_; }

		/**
		 * @brief LogPerfInfo 记录统计信息到日志文件
		 */
		static void LogPerfInfo( PerfMap& rPerfMap, const char* pKey );

	private:

		static PerfMap performance_map_;
	};

	class CPerfClock
	{
	public:
		CPerfClock( const char* name ) : perf_name_( NULL )
		{
			perf_name_ = name;
		}

		~CPerfClock( )
		{
			Stop( );
		}
		
		void Start(  )
		{
			clock_.Start( );	
		}
		void Stop( )
		{
			if( clock_.active( ) == true )
            {
        		CPerfInfo& info = CPerfStat::GetPerfInfo( perf_name_ ); 
        		info.AddCalled( clock_.Stop( ) );    
            }
		}
	private:
		Clock clock_;
		const char* perf_name_;
	};

}//namespace common

// 宏定义隔开
#ifdef USE_PERF_FUN

// 统计函数调用开销
#define PERF_FUNC(funcname, callfunc)\
	do\
	{\
		CPerfInfo& info = CPerfStat::GetPerfInfo(funcname);\
		Clock a;\
		a.Start();\
		callfunc;\
		info.AddCalled(a.Stop());\
	} while (0)

#define PERF_FUNC_RTN( funcname, rtn, callfunc )\
	do					\
	{					\
		CPerfInfo& info = CPerfStat::GetPerfInfo(funcname);     \
		Clock a;					\
		a.Start();					\
		rtn = callfunc;					\
		info.AddCalled(a.Stop());			\
	} while (0)


// 可以返回流逝时间的统计
#define PERF_FUNC_ELAPSED(funcname, callfunc, _elapse )			\
		CPerfInfo& info = CPerfStat::GetPerfInfo(funcname);	\
		Clock a;					\
		a.Start();					\
		callfunc;					\
		info.AddCalled(a.Stop());			\
		_elapse = (int)a.elapsed();			\


// 统计数据写入日志
#define PERF_LOG ::common::CPerfStat::LogPerfInfo( ::common::CPerfStat::GetPerfMap( ), "Perf" ); ::common::CPerfStat::GetPerfMap( ).clear( );

#define PERF_BEGIN( funcname )									\
		::common::Clock funcname##_a;								\
		funcname##_a.Start( );							        \

#define PERF_END( funcname )									\
		::common::CPerfInfo& funcname##_info = ::common::CPerfStat::GetPerfInfo( #funcname );		\
		funcname##_info.AddCalled( funcname##_a.Stop( ) );			\

#define PERF_ALIVE( funcname )		common::CPerfClock funcname##perf_clock( #funcname ); funcname##perf_clock.Start( );

#else

#define PERF_FUNC(funcname, callfunc)	callfunc;
#define PERF_FUNC_RTN( funcname, rtn, callfunc )	rtn = callfunc;
#define PERF_FUNC_ELAPSED(funcname, callfunc, _elapse )		callfunc;
#define PERF_LOG 
#define PERF_BEGIN( funcname )		
#define PERF_END( funcname )	
#define PERF_ALIVE( funcname )

#endif// USE_PERF_FUN

#endif

